/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1/commercial
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may use this file in compliance with the License.
 * Alternatively, if you can't copy with the License, namely if you do not
 * want to provide source code of your modifications to this file, you may
 * negotiate a commercial licence with the initial developer.
 * You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is COID.
 *
 * The Initial Developer of the Original Code is
 * PosAm.
 * Portions created by the Initial Developer are Copyright (C) 2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * Brano Kemen
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#ifndef __COID_SERVER_FILTER__HEADER_FILE__
#define __COID_SERVER_FILTER__HEADER_FILE__


#include "coid/svc/logstream.h"

namespace coid {

////////////////////////////////////////////////////////////////////////////////
class Filter
{
    dynarray<FILTER_ENTRY>  _filters;

    dynarray< dynarray<uint> >  _map;       ///< mapping from object id to applicable filters

public:

    opcd add_filter( const FILTER_ENTRY& flt )
    {
        uint fltid = (uint)_filters.size();
        *_filters.add(1) = flt;

        for( uints i=0; i<flt._ids.size(); ++i )
        {
            uint o = flt._ids[i];
            if( o >= _map.size() )
                _map.need( o+1 );

            *_map[o].add(1) = fltid;
        }

        return 0;
    }

    opcd delete_filter( uint obj, uint fltn )
    {
        if (obj >= _map.size())
            return ersOUT_OF_RANGE "object id";

        if (fltn != UMAX32  &&  fltn >= _map[obj].size())
            return ersOUT_OF_RANGE "filter number";

        if (fltn == UMAX32)
        {
            for (uint i=0; i<_map[obj].size(); ++i)
            {
                uint fltid = _map[obj][i];
                _filters[fltid]._ids.del_key(obj);
            }
            _map[obj].discard();
            return 0;
        }

        uint fltid = _map[obj][fltn];
        _map[obj].del(fltn);

        _filters[fltid]._ids.del_key(obj);
        return 0;
    }

    int passes (const logstream& s) const
    {
        if (s._obj >= _map.size())
            return 1;

        if (_map[s._obj].size() == 0)
            return 1;

        const dynarray<uint>& fltids = _map[s._obj];
        for (uint i=0; i<fltids.size(); ++i)
        {
            if (_filters[fltids[i]].passes(s))
                return 1;
        }

        return 0;
    }

    opcd get_filters (uint obj, uint fltn, dynarray<FILTER_ENTRY>& out) const
    {
        if (obj >= _map.size())
            return ersOUT_OF_RANGE "object id";

        if (fltn != UMAX32  &&  fltn >= _map[obj].size())
            return ersOUT_OF_RANGE "filter number";

        if (fltn == UMAX32)
        {
            out.need_new( _map[obj].size() );
            for (uint i=0; i<_map[obj].size(); ++i)
                out[i] = _filters[_map[obj][i]];
            return 0;
        }

        uint fltid = _map[obj][fltn];
        *out.add(1) = _filters[fltid];

        return 0;
    }

    opcd get_filters (uint obj, uint fltn, dynarray<uint>& out) const
    {
        if (obj >= _map.size())
            return ersOUT_OF_RANGE "object id";

        if (fltn != UMAX32  &&  fltn >= _map[obj].size())
            return ersOUT_OF_RANGE "filter number";

        if (fltn == UMAX32)
        {
            out.need_new( _map[obj].size() );
            for (uint i=0; i<_map[obj].size(); ++i)
                out[i] = _map[obj][i];
            return 0;
        }

        uint fltid = _map[obj][fltn];
        *out.add(1) = fltid;

        return 0;
    }
};

} // namespace coid

#endif //__COID_SERVER_FILTER__HEADER_FILE__
